home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dr. Windows 3
/
dr win3.zip
/
dr win3
/
PROGRAMR
/
OLE2BOOK.ZIP
/
CHAP06.ZIP
/
CHAP06
/
POLYLINE
/
IPERSTOR.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1993-04-14
|
9KB
|
336 lines
/*
* IPERSTOR.CPP
* Polyline Component Object Chapter 6
*
* Implementation of the IPersistStorage interface that we expose on the
* Polyline object.
*
* Copyright (c)1993 Microsoft Corporation, All Rights Reserved
*
* Kraig Brockschmidt, Software Design Engineer
* Microsoft Systems Developer Relations
*
* Internet : kraigb@microsoft.com
* Compuserve: >INTERNET:kraigb@microsoft.com
*/
#include "polyline.h"
/*
* CImpIPersistStorage:CImpIPersistStorage
* CImpIPersistStorage::~CImpIPersistStorage
*
* Constructor Parameters:
* pObj LPVOID pointing to the object we live in.
* punkOuter LPUNKNOWN of the controlling unknown.
*/
CImpIPersistStorage::CImpIPersistStorage(LPVOID pObj, LPUNKNOWN punkOuter)
{
m_cRef=0;
m_pObj=pObj;
m_punkOuter=punkOuter;
return;
}
CImpIPersistStorage::~CImpIPersistStorage(void)
{
return;
}
/*
* CImpIPersistStorage::QueryInterface
* CImpIPersistStorage::AddRef
* CImpIPersistStorage::Release
*
* Purpose:
* Standard set of IUnknown members for this interface
*/
STDMETHODIMP CImpIPersistStorage::QueryInterface(REFIID riid, LPVOID FAR *ppv)
{
return m_punkOuter->QueryInterface(riid, ppv);
}
STDMETHODIMP_(ULONG) CImpIPersistStorage::AddRef(void)
{
++m_cRef;
return m_punkOuter->AddRef();
}
STDMETHODIMP_(ULONG) CImpIPersistStorage::Release(void)
{
--m_cRef;
return m_punkOuter->Release();
}
/*
* CImpIPersistStorage::GetClassID
*
* Purpose:
* Returns the CLSID of the object represented by this interface.
*
* Parameters:
* pClsID LPCLSID in which to store our CLSID.
*
* Return Value:
* HRESULT NOERROR on success, error code otherwise.
*/
STDMETHODIMP CImpIPersistStorage::GetClassID(LPCLSID pClsID)
{
LPCPolyline pObj=(LPCPolyline)m_pObj;
*pClsID=pObj->m_clsID;
return NOERROR;
}
/*
* CImpIPersistStorage::IsDirty
*
* Purpose:
* Tells the caller if we have made changes to this object since
* it was loaded or initialized new.
*
* Parameters:
* None
*
* Return Value:
* HRESULT Contains S_OK if we ARE dirty, S_FALSE if NOT dirty,
* that is, "Yes I AM dirty, or NO, I'm clean."
*/
STDMETHODIMP CImpIPersistStorage::IsDirty(void)
{
LPCPolyline pObj=(LPCPolyline)m_pObj;
return ResultFromScode(pObj->m_fDirty ? S_OK : S_FALSE);
}
/*
* CImpIPersistStorage::InitNew
*
* Purpose:
* Provides the object with the IStorage they can hold on to while
* they are running. Here we can initialize the structure of the
* storage and AddRef it for incremental access. This function will
* only be called once in the object's lifetime in lieu of ::Load.
*
* Parameters:
* pIStorage LPSTORAGE for the object.
*
* Return Value:
* HRESULT NOERROR on success, error code otherwise.
*/
STDMETHODIMP CImpIPersistStorage::InitNew(LPSTORAGE pIStorage)
{
//Nothing to do. We don't need a storage outside ::Load and ::Save.
return NOERROR;
}
/*
* CImpIPersistStorage::Load
*
* Purpose:
* Instructs the object to load itself from a previously saved IStorage
* that was handled by ::Save in another object lifetime. This function
* will only be called once in the object's lifetime in lieu of ::InitNew.
* The object may hold on to pIStorage here for incremental access.
*
* Parameters:
* pIStorage LPSTORAGE from which to load.
*
* Return Value:
* HRESULT NOERROR on success, error code otherwise.
*/
STDMETHODIMP CImpIPersistStorage::Load(LPSTORAGE pIStorage)
{
LPCPolyline pObj=(LPCPolyline)m_pObj;
POLYLINEDATA pl;
ULONG cb;
LPSTREAM pIStream;
HRESULT hr;
if (NULL==pIStorage)
return ResultFromScode(STG_E_INVALIDPOINTER);
//We don't check ClassStg to remain compatible with other chatpers.
//Open the CONTENTS stream
hr=pIStorage->OpenStream("CONTENTS", 0, STGM_DIRECT | STGM_READ
| STGM_SHARE_EXCLUSIVE, 0, &pIStream);
if (FAILED(hr))
return ResultFromScode(STG_E_READFAULT);
//Read all the data into the POLYLINEDATA structure.
hr=pIStream->Read((LPVOID)&pl, CBPOLYLINEDATA, &cb);
pIStream->Release();
if (CBPOLYLINEDATA!=cb)
return ResultFromScode(STG_E_READFAULT);
//CHAPTER6MOD
//DataSet now internal on CPolyline
pObj->DataSet(&pl, TRUE, TRUE);
//End CHAPTER6MOD
return NOERROR;
}
/*
* CImpIPersistStorage::Save
*
* Purpose:
* Saves the data for this object to an IStorage which may
* or may not be the same as the one previously passed to
* ::Load, indicated with fSameAsLoad.
*
* Parameters:
* pIStorage LPSTORAGE in which to save our data.
* fSameAsLoad BOOL indicating if this is the same pIStorage
* that was passed to ::Load. If it was, then
* objects that built up a structure in that storage
* do not have to regenerate the entire thing.
*
* Return Value:
* HRESULT NOERROR on success, error code otherwise.
*/
STDMETHODIMP CImpIPersistStorage::Save(LPSTORAGE pIStorage, BOOL fSameAsLoad)
{
LPCPolyline pObj=(LPCPolyline)m_pObj;
POLYLINEDATA pl;
ULONG cb;
LPSTREAM pIStream;
HRESULT hr;
if (NULL==pIStorage)
return ResultFromScode(STG_E_INVALIDPOINTER);
/*
* fSameAsLoad is not important to us since we always rewrite
* an entire stream as well as the identification tags for this
* object. Note that we don't bother to check the ClassStg
* above in ::Load to remain compatible with other revisions
* of Polyline in other chapters.
*/
WriteClassStg(pIStorage, pObj->m_clsID);
WriteFmtUserTypeStg(pIStorage, pObj->m_cf, (*pObj->m_pST)[IDS_USERTYPE]);
hr=pIStorage->CreateStream("CONTENTS", STGM_DIRECT | STGM_CREATE
| STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pIStream);
if (FAILED(hr))
return ResultFromScode(STG_E_WRITEFAULT);
//CHAPTER6MOD
//DataGet now internal on CPolyline
pObj->DataGet(&pl);
//End CHAPTER6MOD
hr=pIStream->Write((LPVOID)&pl, CBPOLYLINEDATA, &cb);
pIStream->Release();
return (SUCCEEDED(hr) && CBPOLYLINEDATA==cb) ?
NOERROR : ResultFromScode(STG_E_WRITEFAULT);
}
/*
* CImpIPersistStorage::SaveCompleted
*
* Purpose:
* Notifies the object that the storage in pIStorage has been completely
* saved now. This is called when the user of this object wants to
* save us in a completely new storage, and if we normally hang on to
* the storage we have to reinitialize ourselves here for this new one
* that is now complete.
*
* Parameters:
* pIStorage LPSTORAGE of the new storage in which we now live.
*
* Return Value:
* HRESULT NOERROR on success, error code otherwise.
*/
STDMETHODIMP CImpIPersistStorage::SaveCompleted(LPSTORAGE pIStorage)
{
/*
* We have nothing to do here since we do everything in ::Load and
* ::Save. For most objects than handle saves this way, they need
* no code here. Other objects must release their current storage
* here and begin using the new one in pIStorage.
*/
return NOERROR;
}
/*
* CImpIPersistStorage::HandsOffStorage
*
* Purpose:
* Instructs the object that another agent is interested in having total
* access to the storage we might be hanging on to from ::InitNew or
* ::SaveCompleted. In this case we must release our hold and await
* another call to ::SaveCompleted before we have a hold again.
*
* Situations where this might happen arise in compound document scenarios
* where this object might be in-place active but the application wants
* to rename and